﻿using SignalProcessLib.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SignalProcessLib
{
    public class UnitConverter
    {
        private readonly string[] units = { "加速度(m/s2)", "速度(mm/s)", "位移(um)",
                                              "加速度(dB)","速度(dB)", "位移(dB)"};
        public DataFormat Transformer(DataFormat source, String targetUnit)
        {
            DataFormat df = new DataFormat();
            //检查单位是否存在
            int check = 0;
            foreach (string s in units)
            {
                if (source.Unit == s)
                    check++;
            }
            if (check == 0)
                throw new Exception("目标单位不存在");

            //与目标单位一致，则直接返回
            if (source.Unit == targetUnit)
                return source;

            DataFormat temp = new DataFormat();
            switch (targetUnit)
            {
                case "加速度(m/s2)":
                    df = UnitDispatcher(source);
                    break;
                case "速度(mm/s)":
                    df = IntegrationDispatcher(source);
                    break;
                case "位移(um)":
                    temp = IntegrationDispatcher(source);//mm/s
                    df = IntegrationDispatcher(temp);//um
                    break;
                case "加速度(dB)":

                    break;
                case "速度(dB)":
                    temp = IntegrationDispatcher(source);
                    df = UnitDispatcher(temp);
                    break;
                case "位移(dB)":
                    temp = IntegrationDispatcher(source);//mm/s
                    temp = IntegrationDispatcher(temp);//um
                    df = UnitDispatcher(temp);
                    break;
            }

            return df;
        }
        /// <summary>
        /// 单位转换
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public DataFormat UnitDispatcher(DataFormat data)
        {
            DataFormat df = new DataFormat();
            switch (data.Unit)
            {
                //case "dB(m/s2)":
                case "加速度(dB)":
                    df.Y = convertFromdB(data.Y, VibrationConstant.Acc0);
                    df.Unit = "加速度(m/s2)";
                    break;
                case "速度(dB)":
                    df.Y = convertFromdB(data.Y, VibrationConstant.Vel0);
                    df.Unit = "速度(mm/s)";
                    break;
                case "位移(dB)":
                    df.Y = convertFromdB(data.Y, VibrationConstant.Dis0);
                    df.Unit = "位移(um)";
                    break;
                case "加速度(m/s2)":
                    df.Y = convertTodB(data.Y, VibrationConstant.Acc0);
                    df.Unit = "加速度(dB)";
                    break;
                case "速度(mm/s)":
                    df.Y = convertTodB(data.Y, VibrationConstant.Vel0);
                    df.Unit = "速度(dB)";
                    break;
                case "位移(um)":
                    df.Y = convertTodB(data.Y, VibrationConstant.Dis0);
                    df.Unit = "位移(dB)";
                    break;
                default:
                    throw new Exception("该类型无法转换");
            }
            df.X = data.X;
            return df;
        }
        /// <summary>
        /// 积分算法,根据不同的单位进行任务分配
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public DataFormat IntegrationDispatcher(DataFormat data)
        {
            DataFormat df;
            switch (data.Unit)
            {
                case "加速度(m/s2)":
                    df = IntegrationFrequency(data);
                    df.Unit = "速度(mm/s)";
                    break;
                case "速度(mm/s)":
                    df = IntegrationFrequency(data);
                    df.Unit = "位移(um)";
                    break;
                case "加速度(dB)":
                    data.Y = convertFromdB(data.Y, VibrationConstant.Acc0);
                    data.Unit = "加速度(m/s2)";
                    df = IntegrationFrequency(data);
                    //df.Y = convertTodB(df.Y, VibrationConstant.Vel0);
                    df.Unit = "速度(mm/s)";
                    break;
                case "速度(dB)":
                    data.Y = convertFromdB(data.Y, VibrationConstant.Vel0);
                    data.Unit = "速度(mm/s)";
                    df = IntegrationFrequency(data);
                    //df.Y = convertTodB(df.Y, VibrationConstant.Vel0);
                    df.Unit = "位移(um)";
                    break;
                default:
                    throw new Exception("该类型无法积分");
            }
            return df;
        }

        /// <summary>
        /// 将加速度频谱纵坐标单位从dB转换为m/s2
        /// </summary>
        /// <param name="y">输入单位为dB的加速度频谱纵坐标</param>
        /// <returns>返回单位为m/s2的加速度频谱纵坐标</returns>
        public double[] convertFromdB(double[] y, double refer)
        {
            List<double> yl = new List<double>(y);
            return yl.Select(s => Math.Pow(10, s / 20) * refer).ToArray();
        }

        /// <summary>
        /// 将加速度频谱纵坐标单位从m/s2转换为dB
        /// </summary>
        /// <param name="y">单位为m/s2的加速度频谱纵坐标</param>
        /// <returns>单位为dB的加速度频谱纵坐标</returns>
        public double[] convertTodB(double[] y, double refer)
        {
            List<double> yl = new List<double>(y);
            return yl.Select(s => 20 * Math.Log10(s / refer)).ToArray();
        }

        /// <summary>
        /// 频域积分
        /// </summary>
        /// <param name="x">线性频谱横坐标，单位Hz</param>
        /// <param name="y">线性频谱纵坐标，单位</param>
        /// <returns>返回积分后的频谱</returns>
        /// 单位对应关系：加速度单位m/s2--积分--速度单位mm/s
        ///               速度单位mm/s--积分--位移单位um
        public DataFormat IntegrationFrequency(DataFormat data)
        {
            if (data.X.Length != data.Y.Length)
            {
                throw new Exception("横、纵坐标数组长度不一致");
            }
            DataFormat result = new DataFormat();
            result.Y = new double[data.Y.Length];
            for (int i = 0; i < data.X.Length; i++)
            {
                if (data.X[i] == 0)
                    result.Y[i] = 0.0;
                else
                    result.Y[i] = data.Y[i] / (2 * Math.PI * data.X[i]) * 1000;//单位转换
            }
            result.X = data.X;
            return result;
        }
    }
}
